<template>
  <ul class="message-list" ref="messageListRef">
    <li
      :class="message && message.sender === 'user' ? 'ask' : 'answer'"
      v-for="(message, index) in filteredMessages"
      :key="index"
    >
      <!-- 图标部分 -->
      <div :class="message.sender === 'user' ? 'askIcon' : 'answerIcon'">
        <el-icon v-if="message.sender === 'user'">👤</el-icon>
        <el-icon v-else>🤖</el-icon>
      </div>

      <!-- 消息内容部分 -->
      <div
        :class="message.sender === 'user' ? 'askContent' : 'answerContent'"
        style="overflow: visible"
      >
        <!-- 关键修改：移除所有高德地图链接的文本展示（Markdown和纯URL） -->
        <div v-html="renderTextContent(message.text)"></div>
        <div v-if="shouldShowMap(message.text)" class="map-container">
          <!-- 未加载状态：显示加载按钮 -->
          <button
            v-if="
              imageLoadStatus[index] === 'unloaded' ||
              imageLoadStatus[index] === undefined
            "
            @click="startLoadImage(index)"
            class="load-button"
          >
            点击加载地图
          </button>

          <!-- 加载中状态 -->
          <div
            v-if="imageLoadStatus[index] === 'loading'"
            class="loading-overlay"
          >
            <div class="loading-spinner"></div>
            <p>地图加载中...</p>
          </div>

          <!-- 加载成功：显示图片 -->
          <img
            v-if="imageLoadStatus[index] === 'loaded'"
            :src="messageMapUrls[index]"
            alt="路线地图"
            class="map-image"
          />

          <!-- 加载失败状态 -->
          <div v-if="imageLoadStatus[index] === 'error'" class="error-overlay">
            <p>地图加载需要时间,请稍等(大约需10s)...</p>
            <button @click="retryLoadImage(index)">重新加载</button>
          </div>
        </div>
      </div>
    </li>
  </ul>
</template>

<script>
import { ref, watch, onMounted, nextTick, reactive, computed } from "vue";

export default {
  name: "MessageList",
  props: {
    messages: {
      type: Array,
      required: true,
      default: () => [],
    },
  },
  setup(props) {
    const messageListRef = ref(null);

    // 加载状态：unloaded | loading | loaded | error
    const imageLoadStatus = reactive({});
    const errorMessages = reactive({});
    const messageMapUrls = reactive({});
    const messageOriginalUrls = reactive({});

    // 过滤无效消息
    const filteredMessages = computed(() => {
      return props.messages.filter((message) => message && message.text);
    });

    // 自动滚动到底部
    const scrollToBottom = () => {
      if (messageListRef.value) {
        nextTick(() => {
          messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
        });
      }
    };

    // 渲染文本内容：移除地图链接 + 解析Markdown语法
    const renderTextContent = (text) => {
      if (!text) return "";

      // 步骤1：移除所有高德地图链接
      let processedText = text
        .replace(
          /\[.*?\]\(https:\/\/restapi\.amap\.com\/v3\/staticmap[^)]+\)/g,
          ""
        )
        .replace(/https:\/\/restapi\.amap\.com\/v3\/staticmap[^\s<]+/g, "")
        .trim();

      // 步骤2：逐行解析Markdown（支持完整的6级标题）
      const lines = processedText.split(/\r?\n/);
      const htmlLines = lines.map((line) => {
        // 标题：# ~ ###### （修复正则表达式，使用更宽松的匹配方式）
        // 新正则：更宽松地匹配标题格式，确保能正确识别各种标题变体
        const h = line.match(/^\s*(#{1,6})\s+(.+?)\s*$/);
        if (h) {
          const level = h[1].length;
          const cls =
            level === 1
              ? "h1"
              : level === 2
              ? "h2"
              : level === 3
              ? "h3"
              : level === 4
              ? "h4"
              : level === 5
              ? "h5"
              : "h6";

          // 标题内容（处理行内代码/加粗/斜体）
          let inner = h[2].trim(); // 去掉两边的空白

          // 按顺序处理：先处理行内代码，再处理加粗和斜体
          // 避免嵌套冲突，确保代码块内的格式不被错误解析
          inner = inner.replace(/`([^`]+?)`/g, "<code>$1</code>");
          inner = inner.replace(/\*\*([^*]+?)\*\*/g, "<strong>$1</strong>");
          inner = inner.replace(/__([^_]+?)__/g, "<strong>$1</strong>");
          inner = inner.replace(/\*([^\*]+?)\*/g, "<em>$1</em>");
          inner = inner.replace(/_([^_]+?)_/g, "<em>$1</em>");

          return `<h${level} class="markdown-heading ${cls}">${inner}</h${level}>`;
        }
        // 普通行：解析行内代码/加粗/斜体
        let l = line;
        l = l.replace(/`([^`]+?)`/g, "<code>$1</code>");
        l = l.replace(/\*\*([^*]+?)\*\*/g, "<strong>$1</strong>");
        l = l.replace(/__([^_]+?)__/g, "<strong>$1</strong>");
        l = l.replace(/\*([^\*]+?)\*/g, "<em>$1</em>");
        l = l.replace(/_([^_]+?)_/g, "<em>$1</em>");
        return l;
      });
      processedText = htmlLines.join("<br>");

      return processedText || "<span></span>";
    };

    // 检查是否包含高德地图链接（用于决定是否显示地图容器）
    const shouldShowMap = (text) => {
      if (!text) return false;
      return text.includes("https://restapi.amap.com/v3/staticmap");
    };

    // 提取高德地图URL（基于原始消息文本，每次调用都重新提取）
    const extractMapUrl = (text) => {
      if (!text) return null;

      // 匹配Markdown格式 [任意描述](URL)，优先提取
      const markdownRegex = /\[[^\]]+\]\(([^)]+)\)/g;
      let match;
      while ((match = markdownRegex.exec(text)) !== null) {
        if (match[1].includes("restapi.amap.com/v3/staticmap")) {
          return match[1];
        }
      }

      // 匹配纯URL格式
      const urlRegex = /https:\/\/restapi\.amap\.com\/v3\/staticmap[^\s<]+/g;
      const urlMatch = text.match(urlRegex);
      if (urlMatch && urlMatch.length > 0) {
        return urlMatch[0].replace(/[^\w\-.:/?=&%]+$/, ""); // 移除末尾非法字符
      }

      return null;
    };

    // 开始加载地图（每次点击都重新提取URL，确保使用最新链接）
    const startLoadImage = (index) => {
      imageLoadStatus[index] = "loading";
      errorMessages[index] = "";

      const message = filteredMessages.value[index];
      if (!message || !message.text) {
        imageLoadStatus[index] = "error";
        errorMessages[index] = "无效的消息内容";
        return;
      }

      // 核心修复：每次点击都重新提取URL，确保使用当前消息中的最新地图链接
      const rawUrl = extractMapUrl(message.text);
      if (!rawUrl) {
        imageLoadStatus[index] = "error";
        errorMessages[index] = "未找到有效的地图URL";
        return;
      }

      // 更新原始URL和时间戳URL
      messageOriginalUrls[index] = rawUrl;
      const separator = rawUrl.includes("?") ? "&" : "?";
      const timestampUrl = `${rawUrl}${separator}t=${Date.now()}`;
      messageMapUrls[index] = timestampUrl;

      const img = new Image();
      img.onload = () => {
        imageLoadStatus[index] = "loaded";
        scrollToBottom();
      };
      img.onerror = (e) => {
        imageLoadStatus[index] = "error";
        errorMessages[index] = `加载失败：${e.message || "未知错误"}`;
        // console.error(`图片加载失败 [${index}]:`, timestampUrl, e);
      };
      img.src = timestampUrl;
    };

    // 重新加载地图（核心逻辑保持不变）
    const retryLoadImage = (index) => {
      imageLoadStatus[index] = "loading";
      errorMessages[index] = "";

      // 核心修复：重新加载时也重新提取URL，避免使用过时的缓存
      const message = filteredMessages.value[index];
      if (!message || !message.text) {
        imageLoadStatus[index] = "error";
        errorMessages[index] = "无效的消息内容";
        return;
      }

      const rawUrl = extractMapUrl(message.text);
      if (!rawUrl) {
        imageLoadStatus[index] = "error";
        errorMessages[index] = "未找到有效的地图URL";
        return;
      }

      messageOriginalUrls[index] = rawUrl;
      const separator = rawUrl.includes("?") ? "&" : "?";
      const timestampUrl = `${rawUrl}${separator}t=${Date.now()}`;
      messageMapUrls[index] = timestampUrl;

      const img = new Image();
      img.onload = () => {
        imageLoadStatus[index] = "loaded";
      };
      img.onerror = (e) => {
        imageLoadStatus[index] = "error";
        errorMessages[index] = `加载失败：${e.message || "未知错误"}`;
        // console.error(`图片重新加载失败 [${index}]:`, timestampUrl, e);
      };
      img.src = timestampUrl;
    };

    // 初始化消息状态（修复预提取逻辑）
    const initMessageStates = () => {
      filteredMessages.value.forEach((message, index) => {
        if (message && shouldShowMap(message.text)) {
          imageLoadStatus[index] = "unloaded";
          errorMessages[index] = "";

          // 初始化时提取URL并存储
          const rawUrl = extractMapUrl(message.text);
          if (rawUrl) {
            messageOriginalUrls[index] = rawUrl;
          } else {
            console.warn(`初始化时未能提取地图URL，消息索引: ${index}`);
          }
        }
      });
    };

    // 监听消息变化（增强URL提取逻辑）
    watch(
      () => props.messages,
      (newMessages, oldMessages) => {
        const newCount = newMessages.length - oldMessages.length;
        if (newCount > 0) {
          for (let i = oldMessages.length; i < newMessages.length; i++) {
            if (
              newMessages[i] &&
              newMessages[i].text &&
              shouldShowMap(newMessages[i].text)
            ) {
              imageLoadStatus[i] = "unloaded";
              errorMessages[i] = "";

              // 新消息到来时提取URL并存储
              const rawUrl = extractMapUrl(newMessages[i].text);
              if (rawUrl) {
                messageOriginalUrls[i] = rawUrl;
              } else {
                console.warn(`新消息未能提取地图URL，消息索引: ${i}`);
              }
            }
          }
        }
        scrollToBottom();
      },
      { deep: true }
    );

    // 组件挂载初始化
    onMounted(() => {
      initMessageStates();
      scrollToBottom();
    });

    return {
      messageListRef,
      imageLoadStatus,
      errorMessages,
      messageMapUrls,
      shouldShowMap,
      startLoadImage,
      retryLoadImage,
      filteredMessages,
      renderTextContent,
    };
  },
};
</script>

<style scoped>
/* 消息列表样式 */
.message-list {
  max-height: 100%;
  overflow-y: auto;
  padding: 20px;
}

li {
  margin-bottom: 30px;
  display: flex;
  align-items: flex-start;
}

li.ask {
  flex-direction: row-reverse;
}

/* 头像样式 */
.askIcon,
.answerIcon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  flex-shrink: 0;
  margin: 0 15px;
  background: #f0f8ff;
}

/* 消息内容样式 */
.askContent,
.answerContent {
  max-width: 75%;
  border-radius: 20px;
  padding: 20px;
  line-height: 1.6;
  position: relative;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.askContent {
  background-color: #e3f2fd;
  border-bottom-right-radius: 5px;
}

.answerContent {
  background-color: #f5f5f5;
  border-bottom-left-radius: 5px;
}

/* Markdown语法样式（v-html内容需要使用 :deep 解除scoped限制） */
.askContent :deep(.markdown-heading),
.answerContent :deep(.markdown-heading) {
  display: block;
  font-weight: 700;
  margin: 15px 0 10px 0;
  line-height: 1.4;
}

/* 完整6级标题字号定义 */
/* 增强选择器优先级来覆盖base.css的重置样式 */
.askContent h1.markdown-heading.h1,
.answerContent h1.markdown-heading.h1,
.askContent .markdown-heading.h1,
.answerContent .markdown-heading.h1,
.askContent :deep(h1.markdown-heading.h1),
.answerContent :deep(h1.markdown-heading.h1),
.askContent :deep(.markdown-heading.h1),
.answerContent :deep(.markdown-heading.h1) {
  font: normal 1.5em/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    sans-serif !important;
  font-weight: bold !important;
  color: #333 !important;
  border-bottom: 2px solid #e0e0e0 !important;
  padding-bottom: 4px !important;
  margin: 15px 0 10px 0 !important;
  display: block !important;
}

/* 增强选择器优先级来覆盖base.css的重置样式 */
.askContent h2.markdown-heading.h2,
.answerContent h2.markdown-heading.h2,
.askContent .markdown-heading.h2,
.answerContent .markdown-heading.h2,
.askContent :deep(h2.markdown-heading.h2),
.answerContent :deep(h2.markdown-heading.h2),
.askContent :deep(.markdown-heading.h2),
.answerContent :deep(.markdown-heading.h2) {
  font: normal 1.3em/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    sans-serif !important;
  font-weight: 700 !important; /* 使用!important确保覆盖重置样式 */
  color: #333 !important;
  border-left: 4px solid #409eff !important;
  margin: 15px 0 10px 0 !important;
  background-color: rgba(
    64,
    158,
    255,
    0.05
  ) !important; /* 添加背景色增强可见性 */
  padding: 5px 8px 5px 12px !important; /* 统一padding，左侧留出更多空间给边框 */
  display: block !important;
}

/* 增强选择器优先级来覆盖base.css的重置样式 */
.askContent h3.markdown-heading.h3,
.answerContent h3.markdown-heading.h3,
.askContent .markdown-heading.h3,
.answerContent .markdown-heading.h3,
.askContent :deep(h3.markdown-heading.h3),
.answerContent :deep(h3.markdown-heading.h3),
.askContent :deep(.markdown-heading.h3),
.answerContent :deep(.markdown-heading.h3) {
  font: normal 1.3em/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    sans-serif !important;
  font-weight: 700 !important;
  color: #444 !important;
  border-left: 3px solid #67c23a !important;
  margin: 15px 0 10px 0 !important;
  background-color: rgba(103, 194, 58, 0.05) !important;
  padding: 4px 8px 4px 10px !important;
  display: block !important;
}

.askContent :deep(.markdown-heading.h4),
.answerContent :deep(.markdown-heading.h4) {
  font-size: 1.1em;
  font-weight: 600;
  color: #666;
  margin: 10px 0 8px 0;
}

.askContent :deep(.markdown-heading.h5),
.answerContent :deep(.markdown-heading.h5) {
  font-size: 1em;
  font-weight: 600;
  color: #777;
  margin: 8px 0;
}

.askContent :deep(.markdown-heading.h6),
.answerContent :deep(.markdown-heading.h6) {
  font-size: 0.9em;
  font-weight: 600;
  color: #888;
  margin: 8px 0;
}

.askContent :deep(strong),
.answerContent :deep(strong) {
  font-weight: 700;
  color: #1a1a1a;
}

.askContent :deep(em),
.answerContent :deep(em) {
  font-style: italic;
  color: #555;
}

.askContent :deep(code),
.answerContent :deep(code) {
  background-color: rgba(135, 131, 120, 0.15);
  color: #eb5757;
  border-radius: 3px;
  padding: 2px 6px;
  font-family: "Consolas", "Monaco", "Courier New", monospace;
  font-size: 0.9em;
  font-weight: 500;
}

/* 地图容器样式 */
.map-container {
  position: relative;
  margin-top: 15px;
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
  background-color: #f9f9f9;
  min-height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.map-image {
  display: block;
  max-width: 100%;
  max-height: 400px;
  height: auto;
  transition: opacity 0.3s ease;
}

/* 加载按钮样式 */
.load-button {
  padding: 12px 24px;
  background-color: #409eff;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s ease;
}

.load-button:hover {
  background-color: #66b1ff;
}

/* 加载指示器 */
.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 10;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #409eff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 10px;
}

.loading-overlay p {
  color: #666;
  font-size: 16px;
}

/* 错误提示 */
.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 10;
  padding: 20px;
  text-align: center;
}

.error-overlay p {
  color: #f56c6c;
  font-size: 16px;
  margin-bottom: 15px;
}

.debug-info {
  background-color: #f8f8f8;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 10px;
  margin-top: 10px;
  max-width: 100%;
  overflow: auto;
  font-size: 14px;
  text-align: left;
}

.debug-info p {
  margin: 5px 0;
  word-break: break-all;
}

.error-overlay button {
  padding: 10px 20px;
  background-color: #409eff;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.error-overlay button:hover {
  background-color: #66b1ff;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* 响应式调整 */
@media (max-width: 768px) {
  .message-list {
    padding: 10px;
  }

  li {
    margin-bottom: 20px;
  }

  .askIcon,
  .answerIcon {
    width: 35px;
    height: 35px;
    font-size: 20px;
    margin: 0 10px;
  }

  .askContent,
  .answerContent {
    max-width: 70%;
    padding: 15px;
    font-size: 14px;
  }

  .map-container {
    min-height: 250px;
  }

  .debug-info {
    font-size: 12px;
    padding: 5px;
  }
}
</style>